import React, {Component} from 'react'
import numeral from 'numeral'
import _ from 'underscore'
import DefaultLoadingElement from 'lib/util/defaultLoadingElement.jsx'
import DefaultErrorElement from 'lib/util/defaultErrorElement.jsx'
import DefaultNoDataElement from 'lib/util/defaultNoDataElement.jsx'
import {Dispatcher} from 'flux'

export class GradientColor {
  /**
    * 计算分成几步的中间颜色值
    * startColor：开始颜色hex
    * endColor：结束颜色hex
    * step:几个阶级（几步）
    */
  convert(startColor, endColor, step) {
    // 转换为rgb数组模式
    let startRGB = this.colorRgb(startColor);
    let startR = startRGB[0];
    let startG = startRGB[1];
    let startB = startRGB[2];

    let endRGB = this.colorRgb(endColor);
    let endR = endRGB[0];
    let endG = endRGB[1];
    let endB = endRGB[2];

    // 总差值
    let sR = (endR - startR) / step;
    let sG = (endG - startG) / step;
    let sB = (endB - startB) / step;

    let colorArr = [];
    for(let i = 0; i < step; i++) {
      // 计算每一步的 hex 值
      let hex = this.colorHex('rgb(' + parseInt((sR * i + startR)) + ',' + parseInt((sG * i + startG)) + ',' + parseInt((sB * i + startB)) + ')');
      colorArr.push(hex);
    }
    return colorArr;
  }

  /**
    * 将 hex 表示方式转换为 rgb 表示方式(这里返回 rgb 数组模式)
    */
  colorRgb(sColor) {
    let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
    let sColorLower = sColor.toLowerCase();
    if(sColorLower && reg.test(sColorLower)) {
      if(sColorLower.length === 4) {
        let sColorNew = '#';
        for(let i = 1; i < 4; i += 1) {
          sColorNew += sColorLower.slice(i, i + 1).concat(sColorLower.slice(i, i + 1));
        }
        sColorLower = sColorNew;
      }

      //处理六位的颜色值
      let sColorChange = [];
      for(let i = 1; i < 7; i += 2) {
        sColorChange.push(parseInt('0x' + sColorLower.slice(i, i + 2)));
      }
      return sColorChange;
    } else {
      return sColorLower;
    }
  }

  /**
    * 将 rgb 表示方式转换为 hex 表示方式
    */
  colorHex(rgb) {
    let reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6})$/;
    if(/^(rgb|RGB)/.test(rgb)) {
      let aColor = rgb.replace(/(?:(|)|rgb|RGB)*/g, '').split(',');
      let strHex = '#';

      for(let i = 0; i < aColor.length; i++) {
        let hex = Number(aColor[i]).toString(16);
        // 保证每个rgb的值为2位
        hex = hex < 10 ? 0 + '' + hex : hex;

        if(hex === '0') {
            hex += hex;
        }

        strHex += hex;
      }

      if(strHex.length !== 7){
          strHex = rgb;
      }

      return strHex;
    } else if (reg.test(rgb)) {
      let aNum = rgb.replace(/#/, '').split('');

      if (aNum.length === 6){
        return rgb;
      } else if (aNum.length === 3) {
        let numHex = '#';

        for(let i = 0; i < aNum.length; i += 1) {
            numHex += (aNum[i] + aNum[i]);
        }

        return numHex;
      }
    } else {
      return rgb;
    }
  }
}

export default class LateralBlockDiagram extends Component {

  constructor(props, context) {
    super(props, context);

    this.state = {
      defaultHeight:80,
      green:{
        min:'#42BB56',
        max:'#A5E275'
      },
      yellow:{
        min:'#E0F064',
        max:'#E8A000'
      },
      red:{
        min:'#F4A182',
        max:'#E95309'
      }
    }
  }

  prepareData() {
    // debugger
    if (this.props.store.data.length > 10) {
      return (<span>不支持超过 10 项的内容显示！</span>);
    } else {
      // 算法说明：http://wiki.oneapm.me/pages/viewpage.action?pageId=8332527&focusedCommentId=9110583#comment-9110583
      let dataSource = _.chain(this.props.store.data).sortBy('value').map((item) => {
        if (item.value < this.props.green) {
          return _.extend({type: 'green'}, item);
        } else if (item.value >= this.props.green && item.value < this.props.yellow) {
          return _.extend({type: 'yellow'}, item);
        } else {
          return _.extend({type: 'red'}, item);
        }
      }).value();

      let result = [];
      let greenData = _.filter(dataSource, (item) => item.type === 'green');
      {
        result = result.concat(_.chain(greenData)
                                .zip(greenData.length !== 1 ? (new GradientColor().convert(this.state.green.min, this.state.green.max, greenData.length)) : ['#56BC76'])
                                .map(item => _.extend(item[0], {color:item[1]}))
                                .value());
      }

      let yellowData = _.filter(dataSource, (item) => item.type === 'yellow');
      {
        result = result.concat(_.chain(yellowData)
                                .zip(yellowData.length !== 1 ? (new GradientColor().convert(this.state.yellow.min, this.state.yellow.max, yellowData.length)) : ['#EAC85E'])
                                .map(item => _.extend(item[0], {color:item[1]}))
                                .value());
      }

      let redData = _.filter(dataSource, (item) => item.type === 'red');
      {
        result = result.concat(_.chain(redData)
                                .zip(redData.length !== 1 ? (new GradientColor().convert(this.state.red.min, this.state.red.max, redData.length)) : ['#E5603B'])
                                .map(item => _.extend(item[0], {color:item[1]}))
                                .value());
      }

      result = _.filter(result, item => item.ratio !== '0.00%');

      if (result.length === 1) {
        result[0].ratio = '100%';
        return (
          <div
            key={0}
            style={{
              position:'relative',
              width: '100%',
              display:'inline-block',
              height: '36px',
              backgroundColor:result[0].color
            }}
            data-tip={result[0].tip} />
        );
      }

      return result.map((item, index) => {
        if (index === 0) {
          return (
            <div
              key={index}
              style={{
                position:'relative',
                width: item.ratio,
                display:'inline-block',
                height: '36px',
                backgroundColor:item.color
              }}
              data-tip={item.tip} />
          );
        } else {
          return (
            <div
              key={index}
              style={{
                position:'relative',
                width: item.ratio,
                display:'inline-block',
                height: '36px',
                backgroundColor:item.color,
                borderLeft:'1px solid #63748C',
                boxSizing:'border-box'
              }}
              data-tip={item.tip} />
          );
        }
      });
    }
  }

  render() {
    if(this.props.store.loading){
      return <DefaultLoadingElement height={this.state.defaultHeight} />
    }else if(this.props.store.error){
      return <DefaultErrorElement height={this.state.defaultHeight} />
    }else if(this.props.store.data){
      if(this.props.store.data.length){
        let preparedData = this.prepareData();
        let currentStyle = _.extend({
          marginBottom: '14px',
          height:'36px',
          overflow:'hidden'
        }, this.props.style);

        return (<div className="pure-g" style={currentStyle}>{preparedData}</div>);
      }else{
        return <DefaultNoDataElement height={this.state.defaultHeight} />
      }
    }else{
      return null
    }
  }
}

LateralBlockDiagram.defaultProps = {
  // 用于显示成等比时间分布的原始数据
  store: [],
  // 用于附加的额外样式
  style: {},
  // 缺省设置绿色的值，当小于（不包含）的时候，显示为绿色
  green: 100,
  // 缺省设置行色的值，当大于（包含） green 值，并且小于（不包含）当前这个值的时候，显示为黄色；大于（包含）这个值的时候显示为红色
  yellow: 345
}

LateralBlockDiagram.propTypes = {
  store: React.PropTypes.shape({
    // 是否显示等待界面：true 表示显示，优先级最高
    loading: React.PropTypes.bool,
    // 是否显示错误界面：true 表示显示，优先级次之
    error: React.PropTypes.any,
    // 正常数据界面
    data: React.PropTypes.arrayOf(React.PropTypes.shape({
      // 用于检测待显示颜色的值
      value: React.PropTypes.number.isRequired,
      // 用于显示的 tip 信息
      tip: React.PropTypes.string.isRequired,
      // 每段的占比，比如：12%
      ratio: React.PropTypes.string.isRequired,
    }))
  }),
  style: React.PropTypes.object,
  green: React.PropTypes.number,
  yellow: React.PropTypes.number
}
